<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>联机五子棋</title>
    <style>
        * {
            margin: 0;
            padding: 0;
            box-sizing: border-box;
        }

        body {
            font-family: 'Arial', sans-serif;
            background: linear-gradient(135deg, #1a2a6c, #b21f1f, #1a2a6c);
            min-height: 100vh;
            display: flex;
            flex-direction: column;
            align-items: center;
            padding: 20px;
            color: white;
        }

        .container {
            max-width: 800px;
            width: 100%;
            text-align: center;
        }

        header {
            margin-bottom: 20px;
        }

        h1 {
            font-size: 2.5rem;
            margin-bottom: 10px;
            text-shadow: 0 2px 4px rgba(0, 0, 0, 0.5);
        }

        .game-info {
            display: flex;
            justify-content: space-between;
            background: rgba(0, 0, 0, 0.3);
            padding: 15px;
            border-radius: 10px;
            margin-bottom: 20px;
            box-shadow: 0 4px 8px rgba(0, 0, 0, 0.3);
        }

        .player-info {
            display: flex;
            flex-direction: column;
            align-items: center;
        }

        .player-info h3 {
            margin-bottom: 5px;
        }

        .status {
            font-size: 1.2rem;
            font-weight: bold;
            padding: 10px 20px;
            background: rgba(255, 255, 255, 0.1);
            border-radius: 20px;
            margin: 0 20px;
            display: flex;
            align-items: center;
            justify-content: center;
        }

        .game-container {
            display: flex;
            flex-direction: column;
            align-items: center;
            gap: 20px;
        }

        .board {
            display: grid;
            grid-template-columns: repeat(15, 30px);
            grid-template-rows: repeat(15, 30px);
            gap: 0;
            background: #dcb35c;
            padding: 10px;
            border-radius: 5px;
            box-shadow: 0 8px 16px rgba(0, 0, 0, 0.5);
            position: relative;
        }

        .cell {
            width: 30px;
            height: 30px;
            position: relative;
            cursor: pointer;
            display: flex;
            align-items: center;
            justify-content: center;
        }

        .cell::before {
            content: "";
            position: absolute;
            width: 100%;
            height: 1px;
            background: #000;
            top: 50%;
            left: 0;
        }

        .cell::after {
            content: "";
            position: absolute;
            width: 1px;
            height: 100%;
            background: #000;
            left: 50%;
            top: 0;
        }

        .cell.piece::before,
        .cell.piece::after {
            display: none;
        }

        .piece {
            width: 26px;
            height: 26px;
            border-radius: 50%;
            position: relative;
            z-index: 2;
            box-shadow: 0 2px 4px rgba(0, 0, 0, 0.3);
        }

        .black {
            background: radial-gradient(circle at 30% 30%, #666, #000);
        }

        .white {
            background: radial-gradient(circle at 30% 30%, #fff, #ddd);
            border: 1px solid #999;
        }

        .red {
            background: radial-gradient(circle at 30% 30%, #f00, #900);
            border: 1px solid #900;
        }

        .controls {
            display: flex;
            gap: 15px;
            margin-top: 20px;
        }

        button {
            padding: 12px 24px;
            font-size: 1rem;
            border: none;
            border-radius: 30px;
            background: linear-gradient(to right, #4a90e2, #5e60ce);
            color: white;
            cursor: pointer;
            font-weight: bold;
            box-shadow: 0 4px 8px rgba(0, 0, 0, 0.3);
            transition: all 0.3s ease;
        }

        button:hover {
            transform: translateY(-2px);
            box-shadow: 0 6px 12px rgba(0, 0, 0, 0.4);
        }

        button:active {
            transform: translateY(0);
        }

        button:disabled {
            background: #999;
            cursor: not-allowed;
            transform: none;
            box-shadow: none;
        }

        .connection-status {
            margin-top: 15px;
            padding: 10px;
            border-radius: 5px;
            background: rgba(0, 0, 0, 0.3);
        }

        .online-panel {
            background: rgba(0, 0, 0, 0.3);
            padding: 20px;
            border-radius: 10px;
            margin-top: 20px;
            box-shadow: 0 4px 8px rgba(0, 0, 0, 0.3);
        }

        .online-panel h2 {
            margin-bottom: 15px;
        }

        .input-group {
            margin-bottom: 15px;
            display: flex;
            flex-direction: column;
            align-items: center;
            gap: 10px;
        }

        input {
            padding: 10px;
            border-radius: 5px;
            border: none;
            width: 250px;
            font-size: 1rem;
        }

        .win-message {
            position: fixed;
            top: 0;
            left: 0;
            width: 100%;
            height: 100%;
            background: rgba(0, 0, 0, 0.8);
            display: flex;
            flex-direction: column;
            align-items: center;
            justify-content: center;
            z-index: 100;
            font-size: 3rem;
            font-weight: bold;
        }

        .hidden {
            display: none;
        }

        .restart-btn {
            margin-top: 20px;
            font-size: 1.5rem;
            padding: 15px 30px;
        }

        .players-info {
            display: flex;
            justify-content: space-around;
            width: 100%;
            margin-bottom: 20px;
        }

        .player {
            padding: 10px;
            border-radius: 5px;
            background: rgba(255, 255, 255, 0.1);
        }

        .player.current {
            background: rgba(255, 255, 0, 0.3);
            font-weight: bold;
        }

        @media (max-width: 600px) {
            .board {
                grid-template-columns: repeat(15, 20px);
                grid-template-rows: repeat(15, 20px);
            }

            .cell {
                width: 20px;
                height: 20px;
            }

            .piece {
                width: 18px;
                height: 18px;
            }

            h1 {
                font-size: 2rem;
            }
        }
    </style>
</head>
<body>
    <div class="container">
        <header>
            <h1>三人联机五子棋</h1>
        </header>

        <div class="players-info" id="players-info">
            <div class="player" id="player-1">黑子: 等待</div>
            <div class="player" id="player-2">白子: 等待</div>
            <div class="player" id="player-3">红子: 等待</div>
        </div>

        <div class="game-info">
            <div class="status" id="game-status">等待游戏开始</div>
        </div>

        <div class="game-container">
            <div class="board" id="game-board"></div>
            
            <div class="controls">
                <button id="create-game">创建游戏</button>
                <button id="join-game">加入游戏</button>
                <button id="restart-game" disabled>重新开始</button>
            </div>
            
            <div class="connection-status" id="connection-status">
                请创建或加入游戏以开始
            </div>
        </div>

        <div class="online-panel">
            <h2>游戏设置</h2>
            <div class="input-group">
                <input type="text" id="game-id" placeholder="输入游戏ID或留空以创建新游戏">
                <button id="connect-btn">连接</button>
            </div>
        </div>
    </div>

    <div class="win-message hidden" id="win-message">
        <div id="winner-text"></div>
        <button class="restart-btn" id="win-restart">再玩一局</button>
    </div>

    <script>
        class GomokuGame {
            constructor() {
                this.board = Array(15).fill().map(() => Array(15).fill(0));
                this.currentPlayer = 1; // 1 for black, 2 for white, 3 for red
                this.gameOver = false;
                this.gameId = null;
                this.playerId = null;
                this.playerNumber = null; // 1 for black, 2 for white, 3 for red
                this.isMyTurn = false;
                this.websocket = null;
                this.players = {}; // 存储所有玩家信息
                
                this.initializeBoard();
                this.bindEvents();
                this.connectToServer();
            }

            connectToServer() {
                try {
                    // 连接到WebSocket服务器
                    this.websocket = new WebSocket('ws://192.168.11.46:8765');
                    
                    this.websocket.onopen = (event) => {
                        document.getElementById('connection-status').textContent = '已连接到服务器';
                    };
                    
                    this.websocket.onmessage = (event) => {
                        const data = JSON.parse(event.data);
                        this.handleServerMessage(data);
                    };
                    
                    this.websocket.onclose = (event) => {
                        document.getElementById('connection-status').textContent = '与服务器断开连接';
                    };
                    
                    this.websocket.onerror = (error) => {
                        document.getElementById('connection-status').textContent = '连接服务器出错';
                    };
                } catch (error) {
                    document.getElementById('connection-status').textContent = '无法连接到服务器';
                }
            }

            handleServerMessage(data) {
                switch (data.action) {
                    case "game_created":
                        this.handleGameCreated(data);
                        break;
                    case "game_updated":
                        this.handleGameUpdated(data);
                        break;
                    case "game_started":
                        this.handleGameStarted(data);
                        break;
                    case "move_made":
                        this.handleMoveMade(data);
                        break;
                    case "game_restarted":
                        this.handleGameRestarted(data);
                        break;
                    case "opponent_disconnected":
                        this.handleOpponentDisconnected(data);
                        break;
                    case "error":
                        this.handleServerError(data);
                        break;
                }
            }

            handleGameCreated(data) {
                this.gameId = data.game_id;
                this.playerNumber = data.player_number;
                this.isMyTurn = (this.playerNumber === 1); // 黑子先手
                
                document.getElementById('game-id').value = this.gameId;
                document.getElementById('connection-status').textContent = `游戏已创建! 游戏ID: ${this.gameId}`;
                document.getElementById('player-1').textContent = '黑子: 您';
                document.getElementById('player-2').textContent = '白子: 等待';
                document.getElementById('player-3').textContent = '红子: 等待';
                document.getElementById('game-status').textContent = '等待对手加入';
                
                this.updateUI();
            }

            handleGameUpdated(data) {
                this.gameId = data.game_id;
                this.playerNumber = data.player_number;
                
                // 更新玩家信息
                document.getElementById('connection-status').textContent = `已加入游戏，等待其他玩家`;
                
                // 更新玩家列表显示
                for (let i = 1; i <= 3; i++) {
                    const playerElement = document.getElementById(`player-${i}`);
                    const playerInfo = data.player_list.find(p => p.number === i);
                    
                    if (playerInfo) {
                        if (playerInfo.id === this.playerId) {
                            playerElement.textContent = `${this.getPlayerName(i)}: 您`;
                        } else {
                            playerElement.textContent = `${this.getPlayerName(i)}: 对手${i}`;
                        }
                    } else {
                        playerElement.textContent = `${this.getPlayerName(i)}: 等待`;
                    }
                }
                
                document.getElementById('game-status').textContent = `等待${data.players_joined}/${data.total_players}名玩家`;
            }

            handleGameStarted(data) {
                this.gameId = data.game_id;
                this.playerNumber = data.player_number;
                this.currentPlayer = data.current_player;
                this.isMyTurn = (this.playerNumber === this.currentPlayer);
                this.board = data.board;
                
                document.getElementById('connection-status').textContent = `游戏开始!`;
                document.getElementById('game-status').textContent = this.isMyTurn ? '请落子' : `${this.getPlayerName(this.currentPlayer)}落子`;
                
                this.updateBoard();
                this.updatePlayersDisplay();
                this.updateUI();
            }

            handleMoveMade(data) {
                const { row, col, player, current_player, winner, board } = data;
                
                // 更新棋盘状态
                this.board = board;
                this.currentPlayer = current_player;
                this.isMyTurn = (this.playerNumber === this.currentPlayer);
                
                // 在棋盘上放置棋子
                this.placePiece(row, col, player);
                
                // 如果有获胜者
                if (winner) {
                    this.gameOver = true;
                    document.getElementById('restart-game').disabled = false;
                    
                    let winnerText = `${this.getPlayerName(winner)}获胜!`;
                    if (winner === this.playerNumber) {
                        winnerText = `您(${this.getPlayerName(winner)})获胜!`;
                    }
                    
                    document.getElementById('winner-text').textContent = winnerText;
                    document.getElementById('win-message').classList.remove('hidden');
                    document.getElementById('game-status').textContent = winnerText;
                    return;
                }
                
                // 更新状态
                document.getElementById('game-status').textContent = this.isMyTurn ? '请落子' : `${this.getPlayerName(this.currentPlayer)}落子`;
                this.updatePlayersDisplay();
            }

            handleGameRestarted(data) {
                // 重置游戏状态
                this.board = data.board;
                this.currentPlayer = data.current_player;
                this.gameOver = false;
                this.isMyTurn = (this.playerNumber === this.currentPlayer);
                
                // 清空棋盘
                const cells = document.querySelectorAll('.cell');
                cells.forEach(cell => {
                    cell.classList.remove('piece', 'black', 'white', 'red');
                });
                
                // 更新UI
                document.getElementById('restart-game').disabled = true;
                document.getElementById('win-message').classList.add('hidden');
                document.getElementById('game-status').textContent = this.isMyTurn ? '请落子' : `${this.getPlayerName(this.currentPlayer)}落子`;
                this.updatePlayersDisplay();
            }

            handleOpponentDisconnected(data) {
                document.getElementById('connection-status').textContent = '有对手已断开连接';
            }

            handleServerError(data) {
                alert('错误: ' + data.message);
            }

            getPlayerName(playerNumber) {
                switch(playerNumber) {
                    case 1: return '黑子';
                    case 2: return '白子';
                    case 3: return '红子';
                    default: return '未知';
                }
            }

            getPlayerColorClass(playerNumber) {
                switch(playerNumber) {
                    case 1: return 'black';
                    case 2: return 'white';
                    case 3: return 'red';
                    default: return '';
                }
            }

            initializeBoard() {
                const boardElement = document.getElementById('game-board');
                boardElement.innerHTML = '';
                
                for (let row = 0; row < 15; row++) {
                    for (let col = 0; col < 15; col++) {
                        const cell = document.createElement('div');
                        cell.className = 'cell';
                        cell.dataset.row = row;
                        cell.dataset.col = col;
                        cell.addEventListener('click', () => this.handleCellClick(row, col));
                        boardElement.appendChild(cell);
                    }
                }
            }

            updateBoard() {
                // 根据当前棋盘状态更新界面
                for (let row = 0; row < 15; row++) {
                    for (let col = 0; col < 15; col++) {
                        const cellValue = this.board[row][col];
                        if (cellValue !== 0) {
                            this.placePiece(row, col, cellValue);
                        }
                    }
                }
            }

            updatePlayersDisplay() {
                // 更新玩家显示状态
                for (let i = 1; i <= 3; i++) {
                    const playerElement = document.getElementById(`player-${i}`);
                    playerElement.classList.toggle('current', i === this.currentPlayer);
                }
            }

            bindEvents() {
                document.getElementById('create-game').addEventListener('click', () => this.createGame());
                document.getElementById('join-game').addEventListener('click', () => this.joinGame());
                document.getElementById('restart-game').addEventListener('click', () => this.restartGame());
                document.getElementById('connect-btn').addEventListener('click', () => this.connectToGame());
                document.getElementById('win-restart').addEventListener('click', () => this.restartGame());
            }

            createGame() {
                if (!this.websocket || this.websocket.readyState !== WebSocket.OPEN) {
                    alert('未连接到服务器');
                    return;
                }
                
                this.websocket.send(JSON.stringify({
                    action: "create_game"
                }));
            }

            joinGame() {
                if (!this.websocket || this.websocket.readyState !== WebSocket.OPEN) {
                    alert('未连接到服务器');
                    return;
                }
                
                const gameId = document.getElementById('game-id').value;
                if (!gameId) {
                    alert('请输入游戏ID');
                    return;
                }
                
                this.websocket.send(JSON.stringify({
                    action: "join_game",
                    game_id: gameId
                }));
            }

            connectToGame() {
                const gameId = document.getElementById('game-id').value;
                if (gameId) {
                    this.joinGame();
                } else {
                    this.createGame();
                }
            }

            handleCellClick(row, col) {
                // 检查游戏是否结束、是否轮到自己、是否已连接
                if (this.gameOver || !this.isMyTurn || !this.websocket || this.websocket.readyState !== WebSocket.OPEN) {
                    return;
                }

                // 检查格子是否为空
                if (this.board[row][col] !== 0) {
                    return;
                }

                // 发送落子消息到服务器
                this.websocket.send(JSON.stringify({
                    action: "make_move",
                    row: row,
                    col: col
                }));
            }

            placePiece(row, col, player) {
                const cell = document.querySelector(`.cell[data-row="${row}"][data-col="${col}"]`);
                cell.classList.add('piece');
                cell.classList.add(this.getPlayerColorClass(player));
            }

            updateStatus() {
                const statusElement = document.getElementById('game-status');
                if (this.gameOver) return;
                
                if (this.isMyTurn) {
                    statusElement.textContent = '请落子';
                } else {
                    statusElement.textContent = `${this.getPlayerName(this.currentPlayer)}落子`;
                }
            }

            restartGame() {
                if (!this.websocket || this.websocket.readyState !== WebSocket.OPEN) {
                    return;
                }
                
                this.websocket.send(JSON.stringify({
                    action: "restart_game"
                }));
            }

            updateUI() {
                // 更新游戏状态
                this.updateStatus();
                this.updatePlayersDisplay();
            }
        }

        // Initialize the game when the page loads
        document.addEventListener('DOMContentLoaded', () => {
            const game = new GomokuGame();
            window.gomokuGame = game; // Make it available globally for debugging
        });
    </script>
</body>
</html>